#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import datetime

'''
Refer to 
中华人民共和国个人所得税法 
on 国家税务总局(SAT, State Administration of Taxation)
@ http://202.108.90.178/guoshui/action/GetArticleView1.do?id=4087&flag=1
1 不超过500元的 5
2 超过500元至2000元的部分 10
3 超过2000元至5000元的部分 15
4 超过5000元至20000元的部分 20
5 超过20000元至40000元的部分 25
6 超过40000元至60000元的部分 30
7 超过60000元至80000元的部分 35
8 超过80000元至100000元的部分 40
9 超过100000元的部分 45 
'''
BASE_SALARY = 4500
TAX_TABLE = {(0,     500   ) :  5e-2,
             (500,   2000  ) : 10e-2,
             (2000,  5000  ) : 15e-2,
             (5000,  20000 ) : 20e-2,
             (20000, 40000 ) : 25e-2,
             (40000, 60000 ) : 30e-2,
             (60000, 80000 ) : 35e-2,
             (80000, 100000) : 40e-2,
             (100000,888888) : 45e-2}

'''
Terms:
PI,         Pension Isurance
UI,         Unemployment Insurance
MI,         Medical Insurance
II,         Injury Insurance
BI,         Born insurance
PHF,        Publicly accumulated Housing Fund 
SHF,        Supplementary Housing Fund
ER,         Employer
EE,         Employee

Rating Table
    EE  ER
PI  8%  20%
UI  1%  2%
MI  2%  8%
II  0.56%  0
BI  0.56%  0
PHF 7%  15%
'''

# Employer Payment
# 'Item' : (Base, Ratio)
#GROSS_SALARY = 11000
GROSS_SALARY = 12232
# Average Salary of Shanghai employees
# year : value
# In fact:
# 2010 : 3566
AVG_SALARY = {2010 : 2380, 2011 : 3896}

# Insurance and Fund ratio
IFR = {'ER'  : {'PI'  : 20e-2,
                'UI'  : 2e-2,
                'MI'  : 8e-2,
                'II'  : 5.6e-3,
                'BI'  : 5.6e-3,
                'PHF' : 7e-2},
                'SHF' : 8e-2},
       'EE'  : {'PI'  : 8e-2,
                'UI'  : 1e-2,
                'MI'  : 2e-2,
                'PHF' : 7e-2}}

# GROSS_SALARY < AVG_SALARY[2010] x 3, so
PENSION_BASE = AVG_SALARY[2010] * 3
#PENSION_BASE = GROSS_SALARY

class TaxCalculator(object):
    ''' Tax Calculator
    Get the net income after reducing IF and tax from the gross salary.
    '''
    def __init__(self, gross_salary=0):
        object.__init__(self)

        self.cur_year, self.cur_month = datetime.date.today().timetuple()[0:2]
        self.gross_salary = gross_salary
        self.pension_base = 0
        self.net_salary = 0
        self.net_if = 0

        self.taxed_salary = self.gross_salary - self.get_if('EE')
        self.tax = self.get_tax()
        self.net_income = self.taxed_salary - self.tax

    def get_tax(self): 
        ''' Get tax from taxed salary. '''
        ts = self.gross_salary - self.get_if('EE')    # taxed salary
        tax = 0

        taxa = []   # tax list from each tax level
        for [l, r] in sorted(TAX_TABLE.keys(), reverse=True):
            [l, r].sort()
            if l < ts and ts <= r:
                taxa.append((ts - l) * TAX_TABLE[(l, r)])
                ts = l
        tax = sum(taxa)

        return tax 

    def get_if(self, part='EE'):
        ''' Get insurance and fund payed by employee.
        How to calculate insurance and fund?
        1. Base salary
            if your_salary < 3 * city_wide_average_salary_of_last_year
                base_salary = your_salary
            else
                base_salary = 3 * city_wide_average_salary_of_last_year
        2. Ratio
            According to urban law, the ratio of I&F goes as dict IF.
        '''
        try:
            pension_table = IF[part]
        except KeyError, e:
            print 'Key Error:', e
            sys.exit(-1)
        table = dict(pension_table)

        if self.pension_base > 3 * AVG_SALARY[2010]:
            self.pension_base = 3 * AVG_SALARY[2010]
        else:
            self.pension_base = self.gross_salary

        for k in table.keys():
            table[k] = self.pension_base * pension_table[k]

        return sum(table.values())

    def get_netincome(self):
        ic = self.gross_salary - self.get_if('EE') - self.get_tax()
        return ic

    def print_report(self):
        print '───────────────────────────────────'
        print 'IF EE: ¥', float(self.get_if('EE'))
        print 'IF ER: ¥', float(self.get_if('ER'))
        print 'Tax  : ¥', float(self.get_tax())
        print 'Net  : ¥', float(self.get_netincome())
        print '───────────────────────────────────'

    def generate_report(self, type='txt'):
        try:
            of = file('tax_report.' + type, 'w')
        except IOError, e:
            print 'IO Error:', e
            sys.exit(-1)

        of.write('───────────────────────────────────\n')
        of.write('IF EE: ¥')
        of.write(u'' + str(self.get_if('EE')) + '\n')
        of.write('IF ER: ¥')
        of.write(u'' + str(self.get_if('ER')) + '\n')
        of.write('Tax  : ¥')
        of.write(u'' + str(self.get_tax()) + '\n')
        of.write('Net  : ¥')
        of.write(u'' + str(self.get_netincome()) + '\n')
        of.write('───────────────────────────────────\n')

        of.close()

def main():
    global TAX_TABLE
    global BASE_SALARY

    tc = TaxCalculator(GROSS_SALARY)
    tc.print_report()
    tc.generate_report()

if __name__ == '__main__':
    main()

